{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "d7f84f97-5768-46b9-b284-90e00b2b9d18",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "华硕主板新乡地区销售单\n",
      "序号\t型号\t价格\t成交量\t平均值\n",
      "1\tZ系列\t1244\t44556\t1244\n"
     ]
    },
    {
     "ename": "AttributeError",
     "evalue": "'int' object has no attribute 'get'",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mAttributeError\u001b[0m                            Traceback (most recent call last)",
      "Cell \u001b[1;32mIn[7], line 28\u001b[0m\n\u001b[0;32m     26\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m序号\u001b[39m\u001b[38;5;130;01m\\t\u001b[39;00m\u001b[38;5;124m型号\u001b[39m\u001b[38;5;130;01m\\t\u001b[39;00m\u001b[38;5;124m价格\u001b[39m\u001b[38;5;130;01m\\t\u001b[39;00m\u001b[38;5;124m成交量\u001b[39m\u001b[38;5;130;01m\\t\u001b[39;00m\u001b[38;5;124m平均值\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[0;32m     27\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m i,row \u001b[38;5;129;01min\u001b[39;00m df_sales_data\u001b[38;5;241m.\u001b[39miterrows():\n\u001b[1;32m---> 28\u001b[0m     average \u001b[38;5;241m=\u001b[39m average\u001b[38;5;241m.\u001b[39mget(row[\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m型号\u001b[39m\u001b[38;5;124m'\u001b[39m],\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m待定\u001b[39m\u001b[38;5;124m'\u001b[39m) \u001b[38;5;66;03m# 如果型号不在averages中，则显示待定\u001b[39;00m\n\u001b[0;32m     29\u001b[0m     \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mi\u001b[38;5;241m+\u001b[39m\u001b[38;5;241m1\u001b[39m\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;130;01m\\t\u001b[39;00m\u001b[38;5;132;01m{\u001b[39;00mrow[\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m型号\u001b[39m\u001b[38;5;124m'\u001b[39m]\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;130;01m\\t\u001b[39;00m\u001b[38;5;132;01m{\u001b[39;00mrow[\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m价格\u001b[39m\u001b[38;5;124m'\u001b[39m]\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;130;01m\\t\u001b[39;00m\u001b[38;5;132;01m{\u001b[39;00mrow[\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m成交量\u001b[39m\u001b[38;5;124m'\u001b[39m]\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;130;01m\\t\u001b[39;00m\u001b[38;5;132;01m{\u001b[39;00maverage\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m)\n",
      "\u001b[1;31mAttributeError\u001b[0m: 'int' object has no attribute 'get'"
     ]
    }
   ],
   "source": [
    "# 完成销售清单的练习\n",
    "# 完成对华硕主板销售清单的操作\n",
    "import pandas as pd\n",
    "# 给出销售清单\n",
    "sales_data = [{'型号':'Z系列','价格':1244,'成交量':44556},\n",
    "              {'型号':'B系列','价格':1177,'成交量':77665},\n",
    "              {'型号':'H系列','价格':1045,'成交量':12432}]\n",
    "\n",
    "# 将列表中的字典转换为dataframe\n",
    "df_sales_data = pd.DataFrame(sales_data)\n",
    "\n",
    "# 计算平均值\n",
    "average = {}\n",
    "for model in sales_data:\n",
    "    average[model['型号']] = model['价格'] \n",
    "# 简化处理，因为这里价格固定，所以平均值就是价格\n",
    "\n",
    "# 创建E系列主板的数据（成交量为0，平均值待定）\n",
    "e_series = pd.DataFrame({'型号':['E系列'],'价格':[6677],'成交量':[0]})\n",
    "\n",
    "# 使用concat合并dataframe\n",
    "df_sales_data = pd.concat([df_sales_data,e_series],ignore_index=True)\n",
    "\n",
    "# 打印数据表（这里简化处理，不计算E系列的平均值）\n",
    "print('华硕主板新乡地区销售单')\n",
    "print('序号\\t型号\\t价格\\t成交量\\t平均值')\n",
    "for i,row in df_sales_data.iterrows():\n",
    "    average = average.get(row['型号'],'待定') # 如果型号不在averages中，则显示待定\n",
    "    print(f\"{i+1}\\t{row['型号']}\\t{row['价格']}\\t{row['成交量']}\\t{average}\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "12e5b1da-8eb7-4568-ae00-741462ffaab3",
   "metadata": {},
   "source": [
    "区间表示法\n",
    "左闭右开\n",
    "左开右闭\n",
    "闭区间\n",
    "开区间"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "681c3c47-2af3-4a3c-8b59-e3d50bcc5a4c",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1,2,3,4,\n",
      "[20, 30, 40, 50]\n",
      "\n",
      "2,3,4,5,\n",
      "1,2,3,4,5,\n",
      "[1, 2, 3, 4, 5]\n",
      "\n",
      "2,3,4,"
     ]
    }
   ],
   "source": [
    "# 左闭右开区间[1,5)\n",
    "for i in range(1,5):\n",
    "    print(i,end=',')\n",
    "print() # 换行\n",
    "\n",
    "# 使用列表切片\n",
    "list_cut = [10,20,30,40,50,60]\n",
    "print(list_cut[1:5])\n",
    "print() # 换行\n",
    "\n",
    "\n",
    "# 左开右闭区间（1，5]\n",
    "# 需要自定义实现，python没有直接支持\n",
    "def open_closed_range(start,stop):\n",
    "    return range(start+1,stop+1)\n",
    "\n",
    "for i in open_closed_range(1,5):\n",
    "    print(i,end=',')\n",
    "print() # 换行\n",
    "\n",
    "# 闭区间[1,5]\n",
    "for i in range(1,6):\n",
    "    print(i,end=',')\n",
    "\n",
    "print() # 换行\n",
    "# 或者使用列表\n",
    "print(list(range(1,6)))\n",
    "print() # 换行\n",
    "\n",
    "# 开区间(1,5)\n",
    "def open_interval(start,stop):\n",
    "    return range(start+1,stop)\n",
    "\n",
    "for i in open_interval(1,5):\n",
    "    print(i,end=',')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e50dabcb-155e-4f3f-85f9-b4eec37dc4c2",
   "metadata": {},
   "source": [
    "pandas 的索引操作和高级索引\n",
    "索引对象\n",
    "pandas中的索引对象都是index类对象，又称为索引对象，该对象是不可以进行修改的，以保证数据的安全"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "da1c4268-1ffb-4036-aee0-7f7348fe9f20",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Index(['a', 'b', 'c', 'd', 'e'], dtype='object')\n",
      "a    0\n",
      "b    1\n",
      "c    2\n",
      "d    3\n",
      "e    4\n",
      "dtype: int64\n"
     ]
    }
   ],
   "source": [
    "import pandas as pd\n",
    "\n",
    "ser_obj = pd.Series(range(5),index = ['a','b','c','d','e'])\n",
    "ser_index = ser_obj.index\n",
    "print(ser_index)\n",
    "print(ser_obj)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9caff90b-1f0b-42f8-a8ec-008c8b9c0458",
   "metadata": {},
   "source": [
    "虽然index是不可变的，但是可以创造两个series对象共用一个index\n",
    "1、index64index：针对整数特殊index对象\n",
    "2、multlindex：层次化索引，表示单个轴上的多层索引\n",
    "3、datatimeindex：存储纳秒级时间戳"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6cb9d8ad-2c3c-45cb-962b-567aa27e64e9",
   "metadata": {},
   "source": [
    "重置索引\n",
    "pandas中提供了一个重要的方法是reindex，该方法的作用是对原索引和新索引进行匹配，也就是说，新索引包含于原索引的程序，而原索引数据按照新索引排序，如果新索引中没有原索引的数据，那么程序会添加新的索引，并将值填充为nan或者使用fill_value填充其他值\n",
    "reindex方法语法格式\n",
    "\n",
    "DataFrame.reindex(labels+None,index=None,columns=None,axis=None,method=None,\n",
    "                 copy=None,level=None,fill_value=None,limit=None,tolerance=None)\n",
    "index：用作索引的新序列\n",
    "method：插值填充方式\n",
    "fill_value：引入缺失值时使用的替代值\n",
    "limit：前向或后向填充时的最大填充量"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "05629442-7c78-4345-a725-8c233a30e823",
   "metadata": {},
   "source": [
    "fill_value参数会让所有的缺失数据填充为同一个值，如果期望使用相邻元素值（前面或后面元素的值）进行填充，则可以使用method参数，method参数提供多个对应的参数值\n",
    "ffill或pad 前向填充值\n",
    "hfill或backfill  后向填充值\n",
    "nearest 从最近的索引值填充"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "4cecfff0-0707-4c04-94de-6308b7d98e65",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "a    1\n",
      "s    2\n",
      "d    3\n",
      "f    4\n",
      "g    5\n",
      "dtype: int64\n",
      "a    1.0\n",
      "b    NaN\n",
      "c    NaN\n",
      "d    3.0\n",
      "e    NaN\n",
      "dtype: float64\n",
      "a    1\n",
      "b    6\n",
      "c    6\n",
      "d    3\n",
      "e    6\n",
      "dtype: int64\n",
      "0    1\n",
      "2    3\n",
      "4    5\n",
      "6    7\n",
      "dtype: int64\n",
      "0    1\n",
      "1    1\n",
      "2    3\n",
      "3    3\n",
      "4    5\n",
      "5    5\n",
      "dtype: int64\n",
      "0    1\n",
      "1    3\n",
      "2    3\n",
      "3    5\n",
      "4    5\n",
      "5    7\n",
      "dtype: int64\n"
     ]
    }
   ],
   "source": [
    "import pandas as pd\n",
    "\n",
    "ser_obj = pd.Series([1,2,3,4,5],index=['a','s','d','f','g'])\n",
    "print(ser_obj)\n",
    "# 重新索引\n",
    "ser_obj2 = ser_obj.reindex(['a','b','c','d','e'])\n",
    "print(ser_obj2)\n",
    "\n",
    "# 重新索引时指定填充的缺失值\n",
    "ser_obj3 = ser_obj.reindex(['a','b','c','d','e'],fill_value=6)\n",
    "print(ser_obj3)\n",
    "\n",
    "# 创建series对象，并为其指定索引\n",
    "ser_obj4 = pd.Series([1,3,5,7],index=[0,2,4,6])\n",
    "print(ser_obj4)\n",
    "# 向前索引，重新填充值\n",
    "ser_obj5 = ser_obj4.reindex(range(6),method='ffill')\n",
    "print(ser_obj5)\n",
    "# 重新索引，向后填充值\n",
    "ser_obj6 = ser_obj4.reindex(range(6),method='bfill')\n",
    "print(ser_obj6)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7332b185-3241-486b-b6ac-e03ca1430a77",
   "metadata": {},
   "source": [
    "当method参数的值该为bfill时，则表示会使用一个索引对应的数据填充对应的数据填充到缺失值的位置。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "92f0a4f8-5858-4774-ab0e-6222c2f29a07",
   "metadata": {},
   "source": [
    "索引操作"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "id": "d3af3372-47d1-4f79-b810-b92e17838e6b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "a    1\n",
      "b    2\n",
      "c    3\n",
      "d    4\n",
      "e    5\n",
      "dtype: int64\n",
      "..................\n",
      "3\n",
      ".......................\n",
      "c    3\n",
      "d    4\n",
      "dtype: int64\n",
      "c    3\n",
      "d    4\n",
      "e    5\n",
      "dtype: int64\n",
      "a    1\n",
      "c    3\n",
      "d    4\n",
      "dtype: int64\n",
      "a    False\n",
      "b    False\n",
      "c     True\n",
      "d     True\n",
      "e     True\n",
      "dtype: bool\n",
      "c    3\n",
      "d    4\n",
      "e    5\n",
      "dtype: int64\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\abc18\\AppData\\Local\\Temp\\ipykernel_13812\\363774673.py:6: FutureWarning: Series.__getitem__ treating keys as positions is deprecated. In a future version, integer keys will always be treated as labels (consistent with DataFrame behavior). To access a value by position, use `ser.iloc[pos]`\n",
      "  print(ser_obj[2])\n"
     ]
    }
   ],
   "source": [
    "# 使用索引直接获得数据\n",
    "import pandas as pd\n",
    "ser_obj = pd.Series([1,2,3,4,5],index=['a','b','c','d','e'])\n",
    "print(ser_obj)\n",
    "print('..................')\n",
    "print(ser_obj[2])\n",
    "print('.......................')\n",
    "print(ser_obj[2:4])\n",
    "print(ser_obj['c':'e'])  # 使用索引名称来进行切片\n",
    "# 如果希望获取的不是连续的数据，则可以通过不连续的索引来实现\n",
    "ser_obj_indexname = ser_obj[['a','c','d']]\n",
    "print(ser_obj_indexname)\n",
    "# 将布尔值数组索引作为模板筛选数据\n",
    "ser_bool = ser_obj > 2\n",
    "print(ser_bool)\n",
    "# 获取结果为True的数据\n",
    "print(ser_obj[ser_bool])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "3b3e438c-a29c-4e39-99cd-4351059b0ada",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "   a  b   c   d\n",
      "0  0  1   2   3\n",
      "1  4  5   6   7\n",
      "2  8  9  10  11\n",
      "0    1\n",
      "1    5\n",
      "2    9\n",
      "Name: b, dtype: int32\n",
      "<class 'pandas.core.series.Series'>\n",
      "   b   d\n",
      "0  1   3\n",
      "1  5   7\n",
      "2  9  11\n",
      "   a  b  c  d\n",
      "0  0  1  2  3\n",
      "1  4  5  6  7\n",
      "   b   d\n",
      "0  1   3\n",
      "1  5   7\n",
      "2  9  11\n"
     ]
    }
   ],
   "source": [
    "# 也可以通过指定dataframe列索引的操作来处理\n",
    "import pandas as pd\n",
    "import numpy as np\n",
    "\n",
    "arr = np.arange(12).reshape(3,4)\n",
    "# 创建dataframe，并为其指定索引\n",
    "df_obj = pd.DataFrame(arr,columns=['a','b','c','d'])\n",
    "print(df_obj)\n",
    "\n",
    "# 通过索引取值\n",
    "print(df_obj['b'])  # 获取b列的数据\n",
    "print(type(df_obj['b'])) # 查看b列的数据类型\n",
    "\n",
    "# 获取不连续的series对象\n",
    "print(df_obj[['b','d']])\n",
    "\n",
    "# 通过切片获取第0-1行的数据\n",
    "print(df_obj[:2])\n",
    "\n",
    "# 使用多个切片先通过行索引获取第0-1行的数据  \n",
    "# 再通过不连续的列索引获取第b、d列的数据\n",
    "print(df_obj[:3][['b','d']])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "068642ac-d007-4b29-9a97-eb2ba46e2925",
   "metadata": {},
   "source": [
    "虽然dataframe操作索引能够满足基本数据查看要求，但是仍是不够灵活，为此，pandas库汇总提供了操作索引的方法来访问数据，具体为：\n",
    "loc：基于标签索引（索引名称，如a，b等），用于按标签选取数据，当执行切片操作时，即包含起始索引，也包含结束索引\n",
    "iloc：基于位置索引（整数索引，如0到length-1），用于按位置选取数据，当执行切片操作时，只包含起始索引，不包含结束索引\n",
    "iloc：方法主要使用整数来索引数据，而不能使用字符标签来索引数据，而loc方法恰恰相反，它只能使用字符标签来索引数据，而不能使用整数来索引数据。不过，当dataframe对象的行索引或列索引使用的是整数时，则其就可以使用整数来索引"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "49b3a1cf-a26b-4164-b0af-46f4e1b86f0a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "    a   b   c   d\n",
      "0   0   1   2   3\n",
      "1   4   5   6   7\n",
      "2   8   9  10  11\n",
      "3  12  13  14  15\n",
      "    c   a\n",
      "0   2   0\n",
      "1   6   4\n",
      "2  10   8\n",
      "3  14  12\n",
      "    c   a\n",
      "0   2   0\n",
      "1   6   4\n",
      "2  10   8\n",
      "3  14  12\n"
     ]
    }
   ],
   "source": [
    "import pandas as pd\n",
    "import numpy as np\n",
    "arr = np.arange(16).reshape(4,4)\n",
    "dataframe_obj = pd.DataFrame(arr,columns=['a','b','c','d'])\n",
    "print(dataframe_obj)\n",
    "\n",
    "# 获取多列数据\n",
    "dataframe_loc = dataframe_obj.loc[:,['c','a']]\n",
    "print(dataframe_loc)\n",
    "\n",
    "dataframe_iloc = dataframe_obj.iloc[:,[2,0]]\n",
    "# 执行结果时一致的，使用二者均可\n",
    "print(dataframe_iloc)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "afbebbf6-e1c9-474d-82c7-da460117626b",
   "metadata": {},
   "source": [
    "还可以通过loc方法和iloc方法使用花式索引来访问数据"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "42831b29-3599-4751-ad53-19caf0414080",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "    a   b   c   d\n",
      "0   0   1   2   3\n",
      "1   4   5   6   7\n",
      "2   8   9  10  11\n",
      "3  12  13  14  15\n",
      "   b   c\n",
      "1  5   6\n",
      "2  9  10\n",
      "   b   c\n",
      "1  5   6\n",
      "2  9  10\n"
     ]
    }
   ],
   "source": [
    "# 使用花式索引来访问数据\n",
    "import pandas as pd\n",
    "import numpy as np\n",
    "arr = np.arange(16).reshape(4,4)\n",
    "dataframe_obj = pd.DataFrame(arr,columns=['a','b','c','d'])\n",
    "print(dataframe_obj)\n",
    "\n",
    "df_flower_loc = dataframe_obj.loc[1:2,['b','c']]\n",
    "print(df_flower_loc)\n",
    "\n",
    "df_flower_iloc = dataframe_obj.iloc[1:3,[1,2]]\n",
    "print(df_flower_iloc)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ec35f12d-df23-4bbf-a0e9-3d299e2e496f",
   "metadata": {},
   "source": [
    "数据排序\n",
    "由于pandas中存放的时索引和数据的组合，所以它既可以按照索引来进行排序，还可以按数据进行排序"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7a5e6a5f-6554-43da-8021-8343235066e3",
   "metadata": {},
   "source": [
    "按索引排序  \n",
    "sort_index方法可以用行索引或列索引进行排序\n",
    "\n",
    "sort_index(axis = 0,level = None,ascending = True,inplace = False,\n",
    "           kind = 'quicksort',na_position = 'last',sort_remaining = True)\n",
    "axis：轴索引（排序的方向），0表示index（按行），1表示columns（按列）\n",
    "level：若不为none，则指定索引级别的值进行排序\n",
    "ascending：若是升序排序，则默认为true\n",
    "inplace：默认为false，表示对数据进行排序，不创建新的实例\n",
    "kind：选择排序算法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "eaf47641-21c7-4e0a-9d96-90d329a172e9",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "5    10\n",
      "3    11\n",
      "1    12\n",
      "3    13\n",
      "2    14\n",
      "dtype: int64\n",
      "1    12\n",
      "2    14\n",
      "3    11\n",
      "3    13\n",
      "5    10\n",
      "dtype: int64\n",
      "5    10\n",
      "3    11\n",
      "3    13\n",
      "2    14\n",
      "1    12\n",
      "dtype: int64\n"
     ]
    }
   ],
   "source": [
    "import pandas as pd\n",
    "ser_obj = pd.Series(range(10,15),index=[5,3,1,3,2])\n",
    "print(ser_obj)\n",
    "\n",
    "# 按索引进行升序排序\n",
    "ser_obj_sort = ser_obj.sort_index()\n",
    "print(ser_obj_sort)\n",
    "\n",
    "# 按索引进行降序排序\n",
    "ser_obj_sort1 = ser_obj.sort_index(ascending=False)\n",
    "print(ser_obj_sort1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "ae0211c1-0e8a-4ab2-9dfa-0b8217282ea6",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "   0  1  2\n",
      "4  0  1  2\n",
      "3  3  4  5\n",
      "5  6  7  8\n",
      "................\n",
      "   0  1  2\n",
      "3  3  4  5\n",
      "4  0  1  2\n",
      "5  6  7  8\n",
      "................\n",
      "   0  1  2\n",
      "5  6  7  8\n",
      "4  0  1  2\n",
      "3  3  4  5\n"
     ]
    }
   ],
   "source": [
    "# 对dataframe的索引进行排序\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "\n",
    "df_obj = pd.DataFrame(np.arange(9).reshape(3,3),index=[4,3,5])\n",
    "print(df_obj)\n",
    "print('................')\n",
    "\n",
    "# 按索引的升序排序\n",
    "print(df_obj.sort_index())\n",
    "print('................')\n",
    "# 按索引的降序排列\n",
    "print(df_obj.sort_index(ascending=False))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "478f9001-50d9-470c-9501-fbeadb0e6952",
   "metadata": {},
   "source": [
    "按值排序\n",
    "按照排序的方法sort_values()\n",
    "sort_values(by,axis=0,ascending=Ture,inplae=False,kind='quicksort',na_position='last')\n",
    "\n",
    "by：参数表示排序的列\n",
    "na_position：参数只有两个值（first和last），若为first，则会将nan放在开头，若为last，则放在最后\n",
    "\n",
    "需要注意的是当series对象调用sort_values方式进行排序时，所有缺失值都会默认放到末尾\n",
    "在dataframe中，sort_values方法可以根据一个或多个列中的值进行排序，但是需要在排序时将一个或多个列表的索引传递给by参数才行"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "df0ea78c-278e-4eab-b87a-ef25b9662160",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0    4.0\n",
      "1    NaN\n",
      "2    6.0\n",
      "3    NaN\n",
      "4   -3.0\n",
      "5    2.0\n",
      "dtype: float64\n",
      "4   -3.0\n",
      "5    2.0\n",
      "0    4.0\n",
      "2    6.0\n",
      "1    NaN\n",
      "3    NaN\n",
      "dtype: float64\n",
      "2    6.0\n",
      "0    4.0\n",
      "5    2.0\n",
      "4   -3.0\n",
      "1    NaN\n",
      "3    NaN\n",
      "dtype: float64\n"
     ]
    }
   ],
   "source": [
    "import pandas as pd\n",
    "ser_obj = pd.Series([4,np.nan,6,np.nan,-3,2])\n",
    "print(ser_obj)\n",
    "\n",
    "# 按照升序排序\n",
    "print(ser_obj.sort_values())\n",
    "# 按照降序排序\n",
    "print(ser_obj.sort_values(ascending=False))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "681ef5f6-e93e-4469-aa5c-5648d94510c5",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "     0    1    2    3\n",
      "0  0.4 -0.1 -0.3  0.0\n",
      "1  0.2  0.6 -0.1 -0.7\n",
      "2  0.8  0.6 -0.5  0.1\n",
      "...................\n",
      "     0    1    2    3\n",
      "2  0.8  0.6 -0.5  0.1\n",
      "0  0.4 -0.1 -0.3  0.0\n",
      "1  0.2  0.6 -0.1 -0.7\n"
     ]
    }
   ],
   "source": [
    "import pandas as pd\n",
    "df = pd.DataFrame([[0.4,-0.1,-0.3,0.0],[0.2,0.6,-0.1,-0.7],[0.8,0.6,-0.5,0.1]])\n",
    "print(df)\n",
    "print('...................')\n",
    "\n",
    "# 将索引为2的数据进行排序\n",
    "print(df.sort_values(by=2))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b74fde17-a2e2-43e2-83bb-0549992753dc",
   "metadata": {},
   "source": [
    "统计计算与描述\n",
    "pandas提供了很多的数学和统计相关的方法，其中大部分属于汇总统计\n",
    "可以通过axis属性来控制获取的是列还是行 默认是列"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "id": "40f02e31-897f-46ed-8440-05a598a6e7f4",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "   a  b   c   d\n",
      "0  0  1   2   3\n",
      "1  4  5   6   7\n",
      "2  8  9  10  11\n",
      ".................\n",
      "a    12\n",
      "b    15\n",
      "c    18\n",
      "d    21\n",
      "dtype: int64\n",
      ".................\n",
      "a     8\n",
      "b     9\n",
      "c    10\n",
      "d    11\n",
      "dtype: int32\n",
      ".................\n",
      "0    0\n",
      "1    4\n",
      "2    8\n",
      "dtype: int32\n"
     ]
    }
   ],
   "source": [
    "import pandas as pd\n",
    "import numpy as np\n",
    "\n",
    "df_obj = pd.DataFrame(np.arange(12).reshape(3,4),columns=['a','b','c','d'])\n",
    "print(df_obj)\n",
    "print('.................')\n",
    "\n",
    "# 计算每列的和\n",
    "print(df_obj.sum())\n",
    "print('.................')\n",
    "\n",
    "# 计算每列的最大值\n",
    "print(df_obj.max())\n",
    "print('.................')\n",
    "\n",
    "# 沿着横向轴，获取每行的最小值【按照行】\n",
    "print(df_obj.min(axis=1))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1ee96256-5344-45cd-a138-0bf1e793c222",
   "metadata": {},
   "source": [
    "统计描述\n",
    "如果希望一次性的输出多个统计指标，比如平均值、最大值、最小值、求和等，则我们可以调用describe（）方法实现，而不用单独地逐个调用相应的统计方法\n",
    "\n",
    "describe(percentlies=None,include=None,exclude=None)\n",
    "precentiles：输出包含的百分数，一般以小数出现\n",
    "include：指定返回结果的形式\n",
    "exclude：指定返回结果的形式"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "id": "2cc88774-a830-4dc1-a650-29850a8f3b36",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "    0  1   2   3\n",
      "0  12  6 -11  19\n",
      "1  -1  7  50  36\n",
      "2   5  9  23  28\n",
      ".................\n",
      "               0         1          2          3\n",
      "count   3.000000  3.000000   3.000000   3.000000\n",
      "mean    5.333333  7.333333  20.666667  27.666667\n",
      "std     6.506407  1.527525  30.566867   8.504901\n",
      "min    -1.000000  6.000000 -11.000000  19.000000\n",
      "25%     2.000000  6.500000   6.000000  23.500000\n",
      "50%     5.000000  7.000000  23.000000  28.000000\n",
      "75%     8.500000  8.000000  36.500000  32.000000\n",
      "max    12.000000  9.000000  50.000000  36.000000\n"
     ]
    }
   ],
   "source": [
    "import pandas as pd\n",
    "df = pd.DataFrame([[12,6,-11,19],[-1,7,50,36],[5,9,23,28]])\n",
    "print(df)\n",
    "print('.................')\n",
    "# 输出多个统计指标\n",
    "print(df.describe())"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "09b33db6-1350-46a0-bf1b-2ef23a34a528",
   "metadata": {},
   "source": [
    "层次化索引\n",
    "是pandas中索引操作的重点知识概念\n",
    "某公司使用图表绘制了销售额，其中，有一张图为公司销售额的三维柱状图，还\r\n",
    "有一张图为公司销售额的二维柱状图，经过比较发现，两者都能够很好的反映出\r\n",
    "每个月份的销售成本、销售金额和盈利，不过，三维的数据要比二维数据操作更\r\n",
    "麻烦一些\r\n",
    "之前涉及的 Pandas 都只有一层结构（行索引，列索引），又称为单层索引，层\r\n",
    "次化索引可以理解为单层索引的延伸，即在一个轴方向上具有多层索引\r\n",
    "对于两层索引来说，它可以分为内层索引和外层索引，以省\n",
    "                    石家庄市          15848\n",
    "    河北省           唐山市            13472\n",
    "                    邯郸市            12073.8\n",
    "                    秦皇岛市           7813\n",
    "                    郑州市             7446\n",
    "     河南省          开封市             6444\n",
    "                    洛阳市             15230\n",
    "                    新乡市             8269\n",
    "按照从左往右的顺序，位于最左边的一列是省的名称，表示外层索引，位于中间\n",
    "一列的是城市的名称，表示内层索引，位于最右边一列是面积大小，表示数据\r\n",
    "Series 和 DataFrame 都可以实现层次化索引，最常见的方式是在构造法\r\n",
    "index 参数中传入一个嵌\r\n",
    "\n",
    "面积表格为例"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "id": "dfc9a8cf-4be5-4125-aa83-f55f0ff05ae2",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "河北省  石家庄市    15848.0\n",
      "     唐山市     13472.0\n",
      "     邯郸市     12073.8\n",
      "     秦皇岛市    78113.0\n",
      "河南省  郑州市      7446.0\n",
      "     开封市      6444.0\n",
      "     洛阳市     15230.0\n",
      "     新乡市      8264.0\n",
      "dtype: float64\n"
     ]
    }
   ],
   "source": [
    "# 创建具有两层索引的series对象\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "\n",
    "multindex_series = pd.Series([15848,13472,12073.8,78113,7446,6444,15230,8264],\n",
    "                            index=[['河北省','河北省','河北省','河北省','河南省','河南省','河南省','河南省'],\n",
    "                                   ['石家庄市','唐山市','邯郸市','秦皇岛市','郑州市','开封市','洛阳市','新乡市']])\n",
    "print(multindex_series)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4321383b-6e04-4627-9e3c-6ce5e2ec1377",
   "metadata": {},
   "source": [
    "在构造方法创建series对象时，index参数接收了一个嵌套列表来设置索引的层级。其中，嵌套的第一个列表会作为外层索引，而嵌套的第二个列表会作为内层嵌套"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "d4d5aea6-6eab-480c-a81f-ba174e29d48d",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "             占地面积\n",
      "河北省 石家庄市  15848.0\n",
      "    唐山市   13472.0\n",
      "    邯郸市   12073.8\n",
      "    秦皇岛市  78113.0\n",
      "河南省 郑州市    7446.0\n",
      "    开封市    6444.0\n",
      "    洛阳市   15230.0\n",
      "    新乡市    8264.0\n"
     ]
    }
   ],
   "source": [
    "# 创建具有两层索引结构的dataframe对象\n",
    "import pandas as pd\n",
    "from pandas import DataFrame,Series\n",
    "\n",
    "# 占地面积为增加的列索引\n",
    "df = DataFrame({'占地面积':[15848,13472,12073.8,78113,7446,6444,15230,8264]},\n",
    "              index=[['河北省','河北省','河北省','河北省','河南省','河南省','河南省','河南省'],\n",
    "                     ['石家庄市','唐山市','邯郸市','秦皇岛市','郑州市','开封市','洛阳市','新乡市']])\n",
    "print(df)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5a3b9a5d-00b9-45fb-9350-e7c304626bf9",
   "metadata": {},
   "source": [
    "使用dataframe生成层次化索引的方式与series生成层次化索引的方式大致相同，都是对参数index进行设置\n",
    "可以通过multiindex类的方法创建一个层次化索引，multiindex提供了三种创建层次化索引的方法\n",
    "multiindex.from_trples():将元组列表转换为multiindex\n",
    "multiindex.from_arrays():将数组列表转换为multiindex\n",
    "multiindex.from_product():从多个集合的笛卡尔积中创建一个multiindex\n",
    "使用上面的方法都会返回一个multiindex对象，在该对象中有三个比较重要的属性：levels，labels，names\n",
    "levels：表示每个级别的唯一标签\n",
    "labels：表示每一个索引列中每个元素在levels中对应的第几个元素\n",
    "names：可以设置索引等级名称"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "6093f604-6693-4894-b915-db2fca5877ec",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "MultiIndex([('A', 'A1'),\n",
      "            ('A', 'A2'),\n",
      "            ('B', 'B1'),\n",
      "            ('B', 'B2'),\n",
      "            ('B', 'B3')],\n",
      "           names=['外层索引', '内层索引'])\n",
      "           0  1  2\n",
      "外层索引 内层索引         \n",
      "A    A1    1  2  3\n",
      "     A2    8  5  7\n",
      "B    B1    4  8  7\n",
      "     B2    6  3  5\n",
      "     B3    8  9  3\n"
     ]
    }
   ],
   "source": [
    "# 通过from_tuples（）方法创建multiindex对象\n",
    "# from_ tuples方法可以包含若干元组的列表转换为multiindex对象\n",
    "import pandas as pd\n",
    "from pandas import MultiIndex\n",
    "# 创建多个元组的列表\n",
    "list_tuple = [('A','A1'),('A','A2'),('B','B1'),('B','B2'),('B','B3')]\n",
    "# 根据元组列表创建一个multiindex对象\n",
    "multi_index = MultiIndex.from_tuples(tuples=list_tuple,\n",
    "                                      names=['外层索引','内层索引'])\n",
    "print(multi_index)\n",
    "\n",
    "values = [[1,2,3],[8,5,7],[4,8,7],[6,3,5],[8,9,3]]\n",
    "df = pd.DataFrame(data = values,index = multi_index)\n",
    "print(df)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "2152deeb-cb61-4e79-8415-264ab20c093e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "MultiIndex([('A', 'A1'),\n",
      "            ('B', 'A2'),\n",
      "            ('A', 'B1'),\n",
      "            ('B', 'B2'),\n",
      "            ('B', 'B3')],\n",
      "           names=['外层索引', '内层索引'])\n",
      "           0  1  2\n",
      "外层索引 内层索引         \n",
      "A    A1    1  2  3\n",
      "B    A2    8  5  7\n",
      "A    B1    4  8  7\n",
      "B    B2    6  3  5\n",
      "     B3    8  9  3\n"
     ]
    }
   ],
   "source": [
    "# 通过from_arrays方法创建multindex\n",
    "import pandas as pd\n",
    "from pandas import MultiIndex\n",
    "# 根据列表创建一个multiindex对象\n",
    "multi_array = MultiIndex.from_arrays(arrays=[['A','B','A','B','B'],\n",
    "                                            ['A1','A2','B1','B2','B3']],\n",
    "                                    names=['外层索引','内层索引'])\n",
    "print(multi_array)\n",
    "values = [[1,2,3],[8,5,7],[4,8,7],[6,3,5],[8,9,3]]\n",
    "df = pd.DataFrame(data = values,index = multi_array)\n",
    "print(df)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ea9e0527-26e2-4d1c-9470-42f3509e3c88",
   "metadata": {},
   "source": [
    "在创建multiindex对象时，arrays参数接收了一个嵌套列表，表示多层索引的标签，需要注意的是，参数arrays即可以接收列表，又可以接收数组，不过每个列表或数组的长度必须是相同的"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "1cdc4632-05ce-4172-b78f-e843a8653109",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "MultiIndex([(0,  'green'),\n",
      "            (0, 'purple'),\n",
      "            (1,  'green'),\n",
      "            (1, 'purple'),\n",
      "            (2,  'green'),\n",
      "            (2, 'purple')],\n",
      "           names=['number', 'color'])\n",
      "               0  1\n",
      "number color       \n",
      "0      green   7  5\n",
      "       purple  6  6\n",
      "1      green   3  1\n",
      "       purple  5  5\n",
      "2      green   4  5\n",
      "       purple  5  3\n"
     ]
    }
   ],
   "source": [
    "# 通过from_product（）方法创建multiindex对象\n",
    "import pandas as pd\n",
    "import numpy as np\n",
    "from pandas import MultiIndex\n",
    "# 创建\n",
    "numbers = [0,1,2]\n",
    "colors = ['green','purple']\n",
    "multi_product = pd.MultiIndex.from_product(iterables=[numbers,colors],names=['number','color'])\n",
    "print(multi_product)\n",
    "\n",
    "values = np.array([[7,5],[6,6],[3,1],[5,5],[4,5],[5,3]])\n",
    "df = pd.DataFrame(data = values,index = multi_product)\n",
    "print(df)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "09e3a511-19f8-4466-a0b5-18344b4810f5",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "小说    高山上的小邮局     50\n",
      "      失踪的总统       60\n",
      "      绿毛水怪        40\n",
      "散文随笔  浮生六记        94\n",
      "      自在独行        63\n",
      "      皮囊         101\n",
      "传记    铠甲勇士       200\n",
      "      老舍自传        56\n",
      "      库里传         45\n",
      "dtype: int64\n",
      "高山上的小邮局  小说       50\n",
      "失踪的总统    小说       60\n",
      "绿毛水怪     小说       40\n",
      "浮生六记     散文随笔     94\n",
      "自在独行     散文随笔     63\n",
      "皮囊       散文随笔    101\n",
      "铠甲勇士     传记      200\n",
      "老舍自传     传记       56\n",
      "库里传      传记       45\n",
      "dtype: int64\n"
     ]
    }
   ],
   "source": [
    "# 交换索引\n",
    "import pandas as pd\n",
    "from pandas import MultiIndex\n",
    "ser_obj = pd.Series([50,60,40,94,63,101,200,56,45],\n",
    "                    index=[['小说','小说','小说','散文随笔','散文随笔','散文随笔','传记','传记','传记'],\n",
    "                    ['高山上的小邮局','失踪的总统','绿毛水怪','浮生六记','自在独行','皮囊','铠甲勇士','老舍自传','库里传']])\n",
    "print(ser_obj)\n",
    "print(ser_obj.swaplevel())   # 交换内层和外层的索引"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f994b4b3-782c-4d7f-beb9-78fd3d5e5d9c",
   "metadata": {},
   "source": [
    "排序分层\n",
    "要想按照分层索引进行排序，则可以通过sort_index()实现\n",
    "\n",
    "sort_index(axis = 0,level = None,ascending = True,inplace = False,kind = 'quicksort',\n",
    "           na_position = 'last',sort_remining = True,by = None)\n",
    "\n",
    "by：表示按指定的值排序\n",
    "ascending：布尔值，表示是否升序排列，默认为true\n",
    "\n",
    "在使用时，会优先选择外层索引进行排序，然后再按照内层索引进行排序"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "e2e7960f-c610-4697-a125-4e11204fc3d0",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "    word  num\n",
      "A 1    a    1\n",
      "  3    b    2\n",
      "  2    c    4\n",
      "C 3    d    5\n",
      "  1    e    3\n",
      "  2    f    2\n",
      "B 4    g    6\n",
      "  5    h    3\n",
      "  8    i    2\n",
      "    word  num\n",
      "A 1    a    1\n",
      "  2    c    4\n",
      "  3    b    2\n",
      "B 4    g    6\n",
      "  5    h    3\n",
      "  8    i    2\n",
      "C 1    e    3\n",
      "  2    f    2\n",
      "  3    d    5\n",
      "    word  num\n",
      "C 3    d    5\n",
      "  2    f    2\n",
      "  1    e    3\n",
      "B 8    i    2\n",
      "  5    h    3\n",
      "  4    g    6\n",
      "A 3    b    2\n",
      "  2    c    4\n",
      "  1    a    1\n",
      "    word  num\n",
      "B 4    g    6\n",
      "C 3    d    5\n",
      "A 2    c    4\n",
      "C 1    e    3\n",
      "B 5    h    3\n",
      "A 3    b    2\n",
      "C 2    f    2\n",
      "B 8    i    2\n",
      "A 1    a    1\n"
     ]
    }
   ],
   "source": [
    "import pandas as pd\n",
    "from pandas import MultiIndex\n",
    "df_obj = pd.DataFrame({'word':['a','b','c','d','e','f','g','h','i'],'num':[1,2,4,5,3,2,6,3,2]},\n",
    "                     index=[['A','A','A','C','C','C','B','B','B'],[1,3,2,3,1,2,4,5,8]])\n",
    "print(df_obj)\n",
    "\n",
    "# 排序   外层按照字母顺序进行排序，内层按照数字排序\n",
    "print(df_obj.sort_index())  # 升序\n",
    "print(df_obj.sort_index(ascending=False))  # 降序\n",
    "\n",
    "# 按num列降序排列\n",
    "print(df_obj.sort_values(by=['num'],ascending=False))"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
